-- LeiTingAgent
-- Created by lijh Sep/22/2016
-- 雷霆渠道代理

module("LeiTingAgent", package.seeall);

update("game/sdk/LeiTingDataReport")

local PURE_FILE = "LeiTingAgent";

-- 雷霆 iOS 渠道编码映射
-- 注意：渠道名称 leiting 不能随意修改，要保证和 android/LeitingAgent.lua 中 110001 对应的值相同，以确保安卓和iOS可以使用相同的账号登录
local LEITING_CHANNAL_TABLE = {
    ["210009"] = "leiting",    -- 雷霆官网
};

local userInfo = {};

-- 内部函数
local onLeiTingLoginCallback;
local onLeiTingActivateCallback;
local onLeiTingLogoutCallback;
local onLeiTingQuitCallback;
local onLeiTingPaySuccCallback;
local onLeiTingPayFailCallback;
local onLeiTingBindIdCardCallback;
local onRechargeResult;
local whenLoginOk;
local whenCreateNewChar;
local whenUserLevelUp;
local whenPreLoadMainOk;

function init()
    -- 注册登录回调
    SdkMgr.registerOCCallback("onLeiTingLoginCallback", onLeiTingLoginCallback);

    -- 注册激活回调
    SdkMgr.registerOCCallback("onLeiTingActivateCallback", onLeiTingActivateCallback);

    -- 注册登出回调
    SdkMgr.registerOCCallback("onLeiTingLogoutCallback", onLeiTingLogoutCallback);

    -- 注册退出回调
    SdkMgr.registerOCCallback("onLeiTingQuitCallback", onLeiTingQuitCallback);

    -- 注册充值成功回调
    SdkMgr.registerOCCallback("onLeiTingPaySuccCallback", onLeiTingPaySuccCallback);

    -- 注册充值失败回调
    SdkMgr.registerOCCallback("onLeiTingPayFailCallback", onLeiTingPayFailCallback);

    -- 注册绑定身份证回调
    SdkMgr.registerOCCallback("onLeiTingBindIdCardCallback", onLeiTingBindIdCardCallback);

    -- 反注册所有事件
    EventMgr.removeAll("LeiTingAgent");

    -- 注册服务器充值到帐回调
    EventMgr.register("LeiTingAgent", event.RECHARGE_RESULT, onRechargeResult);

    -- 关注玩家登录的事件
    EventMgr.register("LeiTingAgent", event.LOGIN_OK, whenLoginOk);

    -- 关注创建角色的事件
    EventMgr.register("LeiTingAgent", event.CREATE_NEW_CHAR, whenCreateNewChar);

    -- 关注玩家升级的回调
    EventMgr.register("LeiTingAgent", event.USER_LEVEL_UP, whenUserLevelUp);

    -- 关注预加载主场景完毕的事件
    EventMgr.register("LeiTingAgent", event.PRELOAD_MAIN_OK, whenPreLoadMainOk);

    -- 初始化
    callOCFuncWithClass("LeiTingWrap", "initSDK");
end

-- 预加载主场景完毕
function whenPreLoadMainOk()
    -- 检测激活上报
    LeiTingDataReport.checkActiveReport();
end

-- 登录回调
function onLeiTingLoginCallback(param)
    trace(PURE_FILE, "onLeiTingLoginCallback:param = " .. param);

    local ret = string.parseJsonToTable(param);
    local status = ret["status"];
    if status == "1" then
        --登录成功
        processLoginSuccess(ret);
    elseif status == "9" then
        -- 账号需要激活
        activate();

        -- 清除上次登录的渠道记录，并将角色踢回登录界面
        setLastAccountChannel("");
        EventMgr.fire(event.THIRD_ACCOUNT_LOGOUT);
    elseif status == "2" then
        -- 登录失败
        trace(PURE_FILE, "Leiting login failed");

        -- todo:弹框提示
        EventMgr.fire(event.THIRD_ACCOUNT_LOGIN_FAIL, { ["channel"] = CHANNEL_LT });
    end
end

-- 激活回调
function onLeiTingActivateCallback(param)
    trace(PURE_FILE, "onLeiTingActivateCallback:param = " .. param);

    local ret = string.parseJsonToTable(param);
    local status = ret["status"];
    if status == "1" then
        processLoginSuccess(ret);
    elseif status == "0" then
        -- 激活失败
    end
end

-- 执行登录成功的处理，有两种情况：
-- 1. 账号不需要激活时，在登录成功回调中调用
-- 2. 账号需要激活时，在激活成功回调中调用
function processLoginSuccess(ret)
    userInfo = ret;

    local userId    = ret["userId"];
    local channelNo = ret["channelNo"];
    local channel   = getChannel(channelNo);
    trace(PURE_FILE, "Leiting login success, account = %s", userId);

    -- 设置账号信息
    local info = {
        ["account"] = userId,
        ["extra"] = {
            ["3rdplatform"] = channel,
            ["channelNo"]   = channelNo,
        },
        ["extra_raw"] = {
            ["3rdplatform"] = CHANNEL_LT,
            ["channel"]     = channel,
            ["channelNo"]   = channelNo,
            ["game"]        = ret["game"],
            ["userId"]      = userId,
            ["token"]       = ret["token"],
        }
    };
    set3rdAccountLoginInfo(channel, info);

    -- 抛出第三方账号登录事件
    EventMgr.fire(event.THIRD_ACCOUNT_LOGINED, {
        ["channel"] = channel,
        ["loginInfo"] = info,
        ["channel_raw"] = CHANNEL_LT
    });
end

-- 登出回调
function onLeiTingLogoutCallback(param)
    trace(PURE_FILE, "onLeiTingLogoutCallback:param = " .. param);
    -- 清除上次登录的渠道记录
    setLastAccountChannel("");
    EventMgr.fire(event.THIRD_ACCOUNT_LOGOUT);
end

-- 退出回调
function onLeiTingQuitCallback(param)
    trace(PURE_FILE, "onLeiTingQuitCallback:param = " .. param);
end

-- 充值成功回调
-- 注：此回调为扣款回调，不代表服务器已经到账
function onLeiTingPaySuccCallback(param)
    trace(PURE_FILE, "onLeiTingPaySuccCallback:param = " .. param);

    local ret = string.parseJsonToTable(param);
    local status = ret["status"];
    local extInfo = string.parseJsonToTable(ret["extendInfo"]);
    local sku = extInfo["sku"];
    if status == "1" then
        -- 充值成功
        ChargeM.rechargeHandle(sku);
    end
end

-- 充值失败回调
function onLeiTingPayFailCallback(param)
    trace(PURE_FILE, "onLeiTingPaySuccCallback:param = " .. param);

    local ret = string.parseJsonToTable(param);
    local code = ret["code"];
    trace(PURE_FILE, "pay failed with code " .. code);

    -- 充值失败
    EventMgr.fire(event.RECHARGE_FAIL);
end

-- 绑定身份证回调
function onLeiTingBindIdCardCallback(param)
    trace(PURE_FILE, "onLeiTingBindIdCardCallback:param = " .. param);
end

-- 显示登录窗口
function showLogin()
    callOCFuncWithClass("LeiTingWrap", "login");
end

-- 显示个人中心
function showAccountCenter()
    callOCFuncWithClass("LeiTingWrap", "showAccountCenter");
end

-- 切换游戏账号
function switchAccount()
    callOCFuncWithClass("LeiTingWrap", "switchAccount");
end

-- 注销
function logout()
    callOCFuncWithClass("LeiTingWrap", "logout");
end

-- 激活账号
function activate()
    callOCFuncWithClass("LeiTingWrap", "activate");
end

-- 生成用于发送雷霆验证码的 cookie
function generateMobileCookie()
    local userId = userInfo["userId"];
    local dateStr = os.date("%Y%m%d", TimeM.getServerTime());
    local cookie = string.format("(%s%%%s%%%s)", userId, "leiting", dateStr);
    local encryptCookie = string.lower(cc.MD5:getMD5(cookie));

    return encryptCookie;
end

-- 查询是否绑定手机
-- callback : 查询成功后的回调，如果已绑定，则在回调中返回手机号，否则返回nil
function getBindedPhone(callback)
    local sid = userInfo["userId"];         -- 雷霆玩家id
    local cookie = generateMobileCookie();  -- cookie
    local userName = userInfo["userName"];  -- 雷霆玩家名称

    local params = string.format("sid=%s&cookie=%s&username=%s", sid, cookie, userName);

    trace("LeiTingAgent", "getBindedPhone params = " .. params);

    local function myCallback(response)
        trace("LeiTingAgent", "getBindedPhone response = %o", response);

        if callback then
            result = string.parseJsonToTable(response);
            if result["status"] == "1" then
                callback(result["bindPhone"]);
            else
                callback();
            end
        end
    end
    postDataToRemoteHost(LEITING_PHONE_BIND_QUERY_URL, params, myCallback);
end

-- 根据渠道编码获取渠道标识
function getChannel(channelNo)
    return LEITING_CHANNAL_TABLE[channelNo];
end

---------------------
-- 购买商品
-- @param sku 商品库存标识
function buyPurchase(sku)
    function onPrechargeOk(orderId)
        -- 获取商品的价格
        local price = PurchaseToolkit.getProductPrice(sku);
        if price == 0 then
            -- 获取到的价格为零，说明之前拉取商品列表时失败了
            EventMgr.fire(event.RECHARGE_FAIL);
            return;
        end

        local extInfo = {
            sku = sku
        };

        local param = {
            userName = userInfo["userName"],
            userId = userInfo["userId"],
            zoneId = tostring(getCurrentServerId()),    -- 区组Id
            money = tostring(price * 100),              -- 商品价格，以分为单位
            productId = sku,
            orderId = orderId,
            notifyUri = LEITING_PAY_NOTIFY_URL,
            extInfo = json.encode(extInfo),
            roleName = ME.user.dbase:query("name"),
            roleId = ME.user.dbase:query("rid"),
            noShowZone = "1",
        };
        local paramStr = json.encode(param);
        callOCFuncWithClass("LeiTingWrap", "pay", {
            param = paramStr
        });
    end

    local platform   = PUBLISH_TYPE_LT;
    local payChannel = getLastAccountChannel();

    -- 先进行预充值，预充值成功后得到预充值订单号，再通过SDK进行正式充值
    PurchaseToolkit.prePurchase(sku, LEITING_PURCHASE_PRE_URL, platform, payChannel,
        onPrechargeOk, onPrechargeFail);
end

-- 预充值失败
function onPrechargeFail()
    trace(PURE_FILE, "precharge failed");

    -- 充值失败
    EventMgr.fire(event.RECHARGE_FAIL);
end

-- 服务器充值到账
function onRechargeResult(args)
    trace(PURE_FILE, "pay failed with code " .. tostring(args));
end

-- 玩家登录游戏的回调
function whenLoginOk()
    -- 下载商品列表
    PurchaseToolkit.fetchProductsInfo(LEITING_PURCHASE_INFO_FILE_URL, onFetchProductsInfo);

    local param = {
        action = "1",
        roleId = ME.user.dbase:query("rid"),
        roleName = ME.user.dbase:query("name"),
        roleLevel = ME.user.dbase:query("level", 1),
        zoneId = tostring(getCurrentServerId()),
        zoneName = "",
        roleCTime = ME.user:getRoleCreateTime(),
    };

    -- 上报雷霆登录事件
    local paramStr = json.encode(param);
    callOCFuncWithClass("LeiTingWrap", "ltReportLogin", {
        param = paramStr
    });
end

-- 创建新角色的回调
function whenCreateNewChar(args)
    local param = {
        action = "2",
        roleId = ME.user.dbase:query("rid"),
        roleName = ME.user.dbase:query("name"),
        roleLevel = ME.user.dbase:query("level", 1),
        zoneId = tostring(getCurrentServerId()),
        zoneName = "",
        roleCTime = ME.user:getRoleCreateTime(),
    };

    -- 上报雷霆创建角色事件
    local paramStr = json.encode(param);
    callOCFuncWithClass("LeiTingWrap", "ltReportLogin", {
        param = paramStr
    });

    local paramTD = {
        ["type"] = "1",
        ["roleName"] = ""
    };

    -- 上报 Talking Data 创建角色事件
    local paramTDStr = json.encode(paramTD);
    callOCFuncWithClass("LeiTingWrap", "tdReportCreateRole", {
        param = paramStr
    });
end

-- 玩家升级的回调
function whenUserLevelUp(args)
    local level = args.level;
    local rid = ME.user:getRid();
    local name = ME.user:getName();
    local serverId = getCurrentServerId();
    local serverName = getCurrentServerName();
    local roleLevelMTime = TimeM.getServerTime();
    local roleCTime = ME.user:getRoleCreateTime();

    local param = {
        roleId    = rid,                 -- 角色ID
        roleName  = name,                -- 角色名称
        roleLevel = level,               -- 角色等级
        zoneId    = serverId,            -- 区服ID
        zoneName  = serverName,          -- 区服名称
        roleCTime = roleCTime,           -- 角色创建时间
        roleLevelMTime = roleLevelMTime, -- 等级变化时间(选传)
    };

    local paramStr = json.encode(param);

    -- 上报雷霆角色升级事件
    callOCFuncWithClass("LeiTingWrap", "ltReportLevelUp", {
        param = paramStr
    });
end

-- 拉取商品列表信息成功回调
function onFetchProductsInfo(productsInfo)
    for sku, productInfo in pairs(productsInfo) do
        local price = productInfo["price"] .. getLocStr("yuan");
        MarketM.recordSkuPrice(sku, price);
    end
end

-- 获取渠道编码
function getChannelNo()
    return callOCFuncWithClass("LeiTingWrap", "getChannelNo");
end

-- 获取媒体分包编码
function getMedia()
    -- 目前ios没有媒体分包编码
    return "";
end